package com.mmm.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.PageList;
import com.mmm.common.utils.CommonUtils;
import com.mmm.common.utils.EsPage;
import com.mmm.common.vo.Paging;
import com.mmm.user.entity.User;
import com.mmm.user.dao.UserDao;
import com.mmm.user.service.JwtService;
import com.mmm.user.service.TokenService;
import com.mmm.user.service.UserService;
import com.mysql.cj.xdevapi.InsertResult;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.mmm.user.variable.UserVariable.RUSH_USER;

/**
 * (User)表服务实现类
 *
 * @author One
 * @since 2022-03-03 15:25:54
 */
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao userDao;
    @Resource
    private RestHighLevelClient client;
    @Autowired
    private JwtService jwtService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public User queryById(Long id) {
        return this.userDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<User> queryAllByLimit(int offset, int limit) {
        return this.userDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    @Override
    public User insert(User user) {
        try {
            Date date = new Date();
            if (user.getBan() == null) {
                user.setBan(1);
            }
            if (user.getGrade() == null) {
                user.setGrade(5);
            }
            user.setCreateTime(date);
            user.setUpdateTime(date);
            this.userDao.insert(user);
            IndexRequest request = new IndexRequest(RUSH_USER).id(user.getId().toString());
            request.source(JSON.toJSONString(user), XContentType.JSON);

            client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("用户登录失败");
        }
        return user;
    }

    /**
     * 修改数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    @Override
    public User update(User user) {
        user.setUpdateTime(new Date());
        this.userDao.update(user);
        User queryById = this.queryById(user.getId());

        try {
            DeleteRequest deleteRequest = new DeleteRequest(RUSH_USER, queryById.getOpenId().toString());
            client.delete(deleteRequest, RequestOptions.DEFAULT);

            IndexRequest request = new IndexRequest(RUSH_USER).id(queryById.getId().toString());
            request.source(JSON.toJSONString(queryById), XContentType.JSON);
            client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return queryById;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        User user = this.queryById(id);
        user.setDeleteTime(new Date());

        try {
            DeleteRequest request = new DeleteRequest(RUSH_USER).id(id.toString());
            client.delete(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return userDao.update(user) == 1;
    }

    @Override
    public Paging<User> list(Integer page, Integer size) {
        try {
            SearchRequest request = new SearchRequest(RUSH_USER);
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            request.source().query(boolQuery)
                    .sort("updateTime", SortOrder.DESC)
                    .size(size)
                    .from(page);
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            return EsPage.simplePage(User.class, search, page, size);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("user列表搜索失败");
        }


    }

    @Override
    public User findById(Long id) {
        GetRequest request = new GetRequest(RUSH_USER).id(id.toString());
        try {
            GetResponse response = client.get(request, RequestOptions.DEFAULT);
            String source = response.getSourceAsString();
            return JSON.parseObject(source, User.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("用户查找失败 id ：" + id);
        }
    }

    @Override
    public User findByToken(String authorization) {
        Map<String, String> claimMap = jwtService.getClaimMap(authorization);
        String uid = claimMap.get("uid");
        GetRequest request = new GetRequest(RUSH_USER).id(uid.toString());
        try {
            GetResponse response = client.get(request, RequestOptions.DEFAULT);
            String source = response.getSourceAsString();
            return JSON.parseObject(source, User.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("用户查找失败 id ：" + uid);
        }
    }

    @Override
    public User findByOpenId(String openId) {
        return userDao.findByOpenId(openId);
    }

    //    @Override
    public User login(User user) {
        User queryById = userDao.findByOpenId(user.getOpenId());

        if (queryById == null) {
            Date date = new Date();
            user.setCreateTime(date);
            user.setUpdateTime(date);
            int insert = userDao.insert(user);
            if (insert != 1) {
                throw new RuntimeException("user 注册失败");
            }
        } else {
            if (queryById.getBan() == 0) {
                throw new RuntimeException("id为" + user.getId() + "用户已被封号，诺需解封请联系管理员");
            }
        }

        return userDao.findByOpenId(user.getOpenId());

    }

}